﻿using Newtonsoft.Json;
using Sources.Server.Model;
using System.Net.Sockets;
using System.Net;
using System.Text;

namespace Sources.Server.Base
{
    public class ServerSocket
    {
        public Queue<MessageBody> MsgQueue { get; private set; }
        private const int BufferSize = 4096;
        private readonly Socket _server;
        private readonly List<Socket> _clientList;

        public ServerSocket(int port)
        {
            IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddr = ipHost.AddressList[1];
            IPEndPoint localEndPoint = new(ipAddr, port);
            Console.WriteLine(string.Format("Server:{0}:{1}", ipAddr.ToString(), port));
            _server = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _server.Bind(localEndPoint);
            _server.Listen(10);
            _clientList = new();
            MsgQueue = new Queue<MessageBody>();
            new Thread(() =>
            {
                StartListner();
            }).Start();
        }

        private void StartListner()
        {
            while (true)
            {
                Console.WriteLine("Waiting for a connection...");
                Socket handler = _server.Accept();
                _clientList.Add(handler);
                Thread clientThread = new(() => HandleConnection(handler));
                clientThread.Start();
            }
        }

        private void HandleConnection(Socket handler)
        {
            byte[] bytes = new byte[BufferSize];
            StringBuilder data = new();
            while (true)
            {
                int numByte = handler.Receive(bytes);
                data.Append(Encoding.UTF8.GetString(bytes, 0, numByte));
                Console.WriteLine("[Server Got]: " + data);
                try
                {
                    MessageBody message = JsonConvert.DeserializeObject<MessageBody>(data.ToString())!;
                    if (message != null)
                    {
                        MsgQueue.Enqueue(message);
                    }
                }
                catch { }
                data.Clear();
                if (!handler.Connected)
                {
                    break;
                }
            }
        }

        public void SendAll(MessageBody messageBody)
        {
            try
            {
                string jsonStr = JsonConvert.SerializeObject(messageBody);
                byte[] message = Encoding.UTF8.GetBytes(jsonStr);
                foreach (Socket item in _clientList)
                {
                    try
                    {
                        item.Send(message);
                    }
                    catch
                    {
                        Console.WriteLine("[单个客户端]" + jsonStr);
                    }
                }
            }
            catch
            {
                Console.WriteLine("[SendAll Error]" + messageBody.ToString());
            }
        }

        public void Close()
        {
            foreach (Socket item in _clientList)
            {
                try
                {
                    item.Shutdown(SocketShutdown.Both);
                    item.Disconnect(false);
                    item.Close();
                }
                catch
                {

                }
            }
            try
            {
                _server.Shutdown(SocketShutdown.Both);
                _server.Disconnect(false);
                _server.Close();
            }
            catch
            {

            }
        }
    }
}
